import gdata.gcalendar
import gdata.util
import appuifw
import calendar
import e32
import graphics
import os
import time
import e32db

# SYMBIAN_UID=0x01234567
# SIS_VERSION = 1.00

BG_COLOR = (17, 255, 238)
class CalDB:
  def __init__(self, dbfile): 
    self.db = e32db.Dbms()
    try:
      self.db.open(dbfile)
    except:
      self.db.create(dbfile)
      self.db.open(dbfile)
      self.db.execute(u"CREATE TABLE entries (id INTEGER, gid LONG VARCHAR, updated VARCHAR, stamp VARCHAR)")

  def find(self, gevent):
    dbv = e32db.Db_view()
    dbv.prepare(self.db, unicode("SELECT id, updated from entries where gid='%s'"%(gevent._id)))
    dbv.first_line()
    try: 
      dbv.get_line()
      return (dbv.col(1), dbv.col(2))
    except:
      return (None, None)

  def insert(self, gevent, id):
    sql = "INSERT INTO entries (id, gid, updated, stamp) VALUES (%d, '%s', '%s', '%s')" % (id, gevent._id, gevent.updated, time.strftime("%Y%m%d", time.localtime(gevent.end_time)))
    self.db.execute(unicode(sql))
#    print "insert db:%d, %s"%(id, gevent.title)

  def update(self, gevent, id):
    print "update db:%d, %s"%(id, gevent.title)
    sql = "UPDATE entries set updated='%s', stamp='%s', id=%d where gid='%s'"%(gevent.updated, time.strftime("%Y%m%d", time.localtime(gevent.end_time)), id, gevent._id)
    self.db.execute(unicode(sql))

  def clear(self, timestamp):
    self.db.execute(unicode("DELETE FROM entries where stamp<'%s'"%time.strftime("%Y%m%d", time.localtime(timestamp))))

  def close(self):
    self.db.close()

class S60Calendar:
  def __init__(self):
    self.db = calendar.open() 
    
  def add_event(self, gevent):
    if gevent.start_time == None:
#      print "No StartTime:%s"%gevent
      return
    new_entry=self.db.add_appointment() # new appointment.
    new_entry.set_time(gevent.start_time,gevent.end_time)
#    print "set time=%s, %s: %s"%(gevent.start_time,gevent.end_time, gevent.where)
    new_entry.content=gevent.title
    if gevent.where != None:
      new_entry.location=gevent.where
    new_entry.replication='private'
    new_entry.commit()
    return new_entry._unique_id()
  
  def update_event(self, gevent, id):
#    print "=====delete event=%d"%id
    self.db.__delitem__(id)
    return self.add_event(gevent)


  def clear_events(self):
    cnt = 0
    for id in self.db:
      self.db.__delitem__(id)
      cnt = cnt + 1
#    print "Clear events: %d"%cnt

def log(msg):
#  appuifw.note(unicode(msg))
  print msg

img = None
canvas = None
msg = None
def out(imsg):
  global img, canvas, msg
  msg = imsg
  if img:
    img.clear(BG_COLOR)
    img.text((10, 120), unicode(msg))  
    canvas.blit(img)

def showCalendarList(cals):
  opts = []
  opt_cals = []
  for c in cals.get_calendars():
    opts.append(unicode(c.title))
    opt_cals.append(c)
  sels = appuifw.multi_selection_list(opts, 'checkbox', 1)
  scs = []
  for s in sels:
    scs.append(opt_cals[s]) 
  return scs

def handle_redraw(rect):
  global msg
  if msg: 
    out(msg)

#app_lock = None
#
#def quit():
#  global app_lock
#  app_lock.signal()  
  
def main():
  start = time.time()
#  out("GCalSync: start at %d sec"%start)   
  
  appuifw.app.title = u"Google Calendar Sync"
  global canvas
  canvas = appuifw.Canvas(redraw_callback = handle_redraw)
  appuifw.app.body = canvas
  appuifw.app.screen = "normal"
#  appuifw.app.exit_key_handler = quit
  w, h = canvas.size
  global img
  img = graphics.Image.new((w, h))
  out("Welcome to Google Calendar Sync")
#  appuifw.note(unicode(os.getcwd()))
#  bgimg = graphics.Image.open(unicode(os.getcwd()+'\\Images\\logo.gif'))
#  iw, ih = bgimg.size
#  canvas.blit(bgimg, (0,0), ((w-iw)/2, 10)) 
#  canvas.blit(simg)


  id, pwd = gdata.util.user_auth()
#  print id, "=", pwd
  gdata.util.set_accesspoint()
  out("Authenticating....")
  gcal = gdata.gcalendar.GoogleCalendarAPI(id, pwd)
#  log("Auth=%s" % gcal.get_auth())
  out("Authenticating....")
  if gcal.get_auth() == None:
    log("Authentication Error")
  else:    
    out("Calendar List Loading")
    cals = gcal.get_all_calendars()
    sels = showCalendarList(cals)
    if sels != None:
      range = 30*24*60*60
      now = time.gmtime()
      week = time.gmtime(time.time()+range)
      scal = S60Calendar()
#      scal.clear_events()
      db = CalDB(u"c:\\gcal.db")
      db.clear(time.time()-range)
      add = 0
      update = 0
      for cal in sels:
        out("Calendar %s Loading"%cal.title)
  #    log cal.get_content()
        for e in cal.get_events(time.strftime("%Y-%m-%d", now),time.strftime("%Y-%m-%d", week)):
#        print "%s=%s--%s, %s"%(e.title, e.start_time, e.end_time, e.where)
          (eid, updated) = db.find(e)
          if eid == None:
            eid = scal.add_event(e)
            db.insert(e, eid)
            add = add + 1
          else:
            if updated != e.updated:
              eid = scal.update_event(e, eid)
              db.update(e, eid)
              update = update + 1        
      db.close()
      out("Sync done! new items:%d, updated items:%d"%(add, update))
  end = time.time()
#  out("GCalSync end at %(end) sec, total=%(total) secs" % {"end":end, "total":(end - start)})
  out("GCalSync end: total=%(total) secs" % {"total":(end - start)})
#  global app_lock
#  app_lock = e32.Ao_lock()
#  app_lock.wait()    
  
if __name__ == "__main__":
  main()